# -*- coding: UTF-8 -*-
'''
Created on 05.02.2013 

@author: p.hess
'''
from time import time

import SetEnv as env  # build global variables for pathes

import sys

from spreads.LinearSpreadGen import LinearSpread 
from spreads.CircularSpreadGen import CircularSpread
from value.Transform import Transform
from objects3d.Quad import Quad
from animation.Animation import LFO
from value.Value import WaveShaper

from pi3d import Display
from pi3d.Camera import Camera
from pi3d.Keyboard import Keyboard
from pi3d.util.Screenshot import screenshot
from pi3d.Texture import Texture
from pi3d.Shader import Shader


class SpreadIt():
    
    def __init__(self):
        self.KeyboardQueue = None
        
    def setup(self):
        
        #
        # Setup Pi3D
        #
        
        self.DISPLAY = Display.create(0, 0) 
        #self.DISPLAY = Display.create(800,600)
        # now we need a background color. We select black and a 
        # non opaque 
        self.DISPLAY.set_background(0, 0, 0, 1)  # r,g,b,alpha -> black background
        
        #
        # DISPLAY.frames_per_second
        #
        self.DISPLAY.frames_per_second = 25
        
        #
        # Setup keyboard handling
        #

        self.mykeys = Keyboard()        

        print "keyboard handling established" + '\n\r'


    def teardown(self):
        
        #
        # ensure, that all output is written to the display
        #
        # sys.stdout.flush()
        
        #
        # down Pi3d
        #    
        self.DISPLAY.destroy()
        print "teardown Pi3d done"  + '\n\r'           
  
  
    def loop(self):    

        print "enter main loop"

        self.prepareSpreadableObjects()
        
        # do the first inisitalisation        
        
        self.keyboardControlledSpreadcount = 5
        self.keyboardControlledRotation = 0.0
        self.keyboardControlledNoDraw = False
        
        lasttime = time()
        loopCounter = 0
        # quit() # to see shader compile errors, quit here
        while self.DISPLAY.loop_running():
            loopCounter += 1            
            
            self.computeFrame();
            
            # read keyboard not every loop. Slows down the loop            

            if (loopCounter % 1 == 0) :
                                
                k = self.mykeys.read()
                if k > -1:
                    if k == 112: screenshot("earthPic.jpg")    
                    elif k == 27: break # do end processing, finito, go to weekend
                    elif k==119:  # key w
                        self.keyboardControlledRotation -= 0.1
                        if (self.keyboardControlledRotation < 0): self.keyboardControlledRotation = 1
                    elif k==115: # key s
                        self.keyboardControlledRotation += 0.1
                        if (self.keyboardControlledRotation > 1): self.keyboardControlledRotation = 0
                    elif k == 97:  # key a
                        self.keyboardControlledSpreadcount -= 1 
                        if (self.keyboardControlledSpreadcount < 1): self.keyboardControlledSpreadcount = 1
                    elif k == 100: self.keyboardControlledSpreadcount += 1  # keay d
                    elif k == 110: self.keyboardControlledNoDraw = not self.keyboardControlledNoDraw  # key n
                    else: 
                        print "not processed key:" + str(k) + '\n\r'
    
                if (loopCounter % 100 == 0) :
                    currtime = time()
                    loopsPerSecond = 100.0 / (currtime - lasttime)
                    sys.stdout.write(str(time()) + "-" + str(loopCounter) + "-lps: " + str(loopsPerSecond) + '\n\r')
                    lasttime = currtime

            Camera.instance().was_moved = False
            
        print "exit main loop"  + '\n\r'


    def prepareSpreadableObjects(self):
        '''Creates all the objects which are used in the computeFrame() method'''
        
        # Low Frequency Oscilators.
        self.LFOQuad                = LFO(Period_in=7.0)
        self.LFOSphere              = LFO(Period_in=69.0)
        self.WaveShaperSphere       = WaveShaper()
        self.LFOShaderCustomData    = LFO(Period_in=2.0)
        self.LFOMouseMovement       = LFO(Period_in=20.0)
        self.LFODeformer1           = LFO(Period_in=5.1)
        self.LFODeformer2           = LFO(Period_in=5.0)
        self.WaveShaderCustomData   = WaveShaper()
        self.WaveShaperDeformer1    = WaveShaper()
        self.WaveShaperDeformer2    = WaveShaper()
        self.LinearSpreadQuad       = LinearSpread()
        self.LinearSpreadSphere     = LinearSpread()
        self.CircularSpreadShader   = CircularSpread(SpreadCount_in=[1]) 
        self.TransformQuad          = Transform()
        self.TransformSphere        = Transform()
       
        # theShader1 = Shader(env.PI3D_SHADERS_PATH + "/dyn_twist")
        # theShader = Shader("spreadit/shaders/dyn_monjori")
        theShader2 = Shader(env.SPREADIT_SHADERS_PATH + "/dyn_radial_blur")
        sys.stdout.flush()
        # quit();
        # he builder of the Quads (planes)
        # tex = Texture("textures/Raspi256x256.png")
        # tex = Texture("textures/world_map256x256.jpg")
        # tex = Texture("textures/COFFEE.PNG")
        tex = Texture(env.PI3D_TEXTURES_PATH + "/TECHY1.PNG")
        
        #self.Sphere = Sphere(Textures_in = [tex], 
        #                     Shaders_in=[theShader2] ) 
        self.Quad = Quad( Textures_in = [tex], 
                          Shaders_in=[theShader2])  
        
        self.tm = 0.0
        self.dt = 0.01
        self.sc = 0.0
        self.ds = 0.011
        
 
    def computeFrame(self):
        '''compute the next frame to show'''
        
        # on keypress, redraw only (freeze)
        if self.keyboardControlledNoDraw == True:
            self.Sphere.update(transform=self.Transform.transform_out)
            self.SphereInner.update(transform=self.TransformInner.transform_out)
            return;

        ### get the next LFO values for this frame ###
        self.LFOQuad.update()
        self.LFOSphere.update()
        self.LFODeformer1.update()
        self.LFODeformer2.update()
        self.LFOMouseMovement.update()
        
        self.WaveShaperSphere.update(Input_in=self.LFOSphere.Output)
        self.WaveShaperDeformer1.update(Input_in=self.LFODeformer1.Output)
        self.WaveShaperDeformer2.update(Input_in=self.LFODeformer2.Output)
        
        self.LFOShaderCustomData.update()
        self.WaveShaderCustomData.update(Input_in=self.LFOShaderCustomData.Output)
        
        self.LinearSpreadQuad.update(SpreadCount_in=[1])
        self.LinearSpreadSphere.update(SpreadCount_in=[1])
        
        #self.CircularSpreadShader.update(Width_in = [self.DISPLAY.max_width * self.WaveShaperDeformer2.Output[0] * .75],
        #                                 Height_in= [self.DISPLAY.max_height * self.WaveShaperDeformer1.Output[0] * .75],
        #                                 Phase_in = [self.LFOMouseMovement.Output] )
        
        self.TransformQuad.update(  ScaleX_in       = [1.2],
                                    ScaleY_in       = [1.2],
                                    # Rotate_in       = self.LFOQuad.output)
                                    Rotate_in       = [0.0])
       
        
                #----------
        #uniform float time =========> unif[16][0] tm
        #uniform float fScale =======> unif[16][1] sc
        #uniform float fOriginShift => unif[16][2] -0.5 * sc


        #uniform float time =========> unif[16][0] tm
        #uniform float fScale =======> unif[16][1] sc
        #uniform float fOriginShift => unif[16][2] -0.5 * sc
        # self._Sphere.set_custom_data(48,)
        #----------
        
        
        self.TransformSphere.update(    ScaleX_in   = [.5],
                                        ScaleY_in   = [.5],
                                        Rotate_in       = [0.0])
                                        # Rotate_in   = self.WaveShaperSphere.Output)
        width = self.DISPLAY.max_width
        height = self.DISPLAY.max_height 
        #mousex = self.CircularSpreadShader.OutputX[0] + (width / 2)
        #mousey = self.CircularSpreadShader.OutputY[0] + (height / 2 )
        #self.Sphere.update(Transform=self.TransformSphere.transform_out,
        #                   ShaderCustomData= [self.tm, self.sc, -0.5 * self.sc, # base values
        #                                      #self.WaveShaderCustomData.Output*width, self.WaveShaderCustomData.Output*height, 0.0,               # mouse position
        #                                      width, height, 0.0,               # resolution)
        #                                      #mousex, mousey, 0.0               # mouse position
        #                                      ])       
        self.Quad.update(Transform=self.TransformQuad.transform_out,
                         ShaderCustomData= [self.tm, self.sc, -0.5 * self.sc, # base values
                                              #self.WaveShaderCustomData.Output*width, self.WaveShaderCustomData.Output*height, 0.0,               # mouse position
                                              width, height, 0.0,               # resolution)
                                              #mousex, mousey, 0.0               # mouse position
                                              ]) 
        
        # self.tm += self.dt
        self.ds = self.LFOQuad.Output[0] / 100
        #self.tm = self.LFOShaderCustomData.Output[0] 
        self.tm += .1
        self.sc = (self.sc + self.ds) % 10.0


# end class --------------------------------------------------------------------------------------------
    
mySpreadIt = SpreadIt()
mySpreadIt.setup()
mySpreadIt.loop()
mySpreadIt.teardown()

